﻿//using System;
//using System.Collections.Generic;
//using System.Drawing;
//using Petra.Gis.Geometry.Support;

//namespace Petra.Gis.RenderingServices.PlanarBase 
//{


//  public abstract class PlanarMapExtent
//  {


//    public enum EdgeName
//    {
//      left = 2, bottom = 8, right = 1, top = 4
//    }

//    protected PlanarMap _parentMap;

    
//    protected double[] _Bbox = new double[9];
//    protected int[] _ScrBbox = new int[9];
//    //protected DisplayTransformMatrix _transMatrix;

//    //public MapExtent(PlanarMap parentMap, BoundingBox crsBounds, DisplayTransformMatrix transform)
//    //  : this(parentMap, crsBounds.Left, crsBounds.Bottom, crsBounds.Right, crsBounds.Top, transform)
//    public PlanarMapExtent(PlanarMap parentMap, BoundingBox crsBounds)
//      : this(parentMap, crsBounds.Left, crsBounds.Bottom, crsBounds.Right, crsBounds.Top)
//    {
//    }


//    //public MapExtent(PlanarMap parentMap, double worldLeft, double worldBottom, double worldRight, double worldTop, DisplayTransformMatrix transform)
//    public PlanarMapExtent(PlanarMap parentMap, double worldLeft, double worldBottom, double worldRight, double worldTop)
//    {

//      _parentMap = parentMap;

//      //validate
//      if (!isValid(worldLeft, worldBottom, worldRight, worldTop))
//        throw new ArgumentException("invalid bbox values", "left, right, top, bottom");

//      _Bbox[2] = worldLeft;
//      _Bbox[8] = worldBottom;
//      _Bbox[1] = worldRight;
//      _Bbox[4] = worldTop;


//      _transMatrix = new DisplayTransformMatrix();
//      Resize(parentMap.Width, parentMap.Height);

//      //_transMatrix = transform;

//      Point tmp = _transMatrix.TransformPoint(worldLeft, worldBottom);
//      _ScrBbox[2] = tmp.X;
//      _ScrBbox[8] = tmp.Y;

//      tmp = _transMatrix.TransformPoint(worldRight, worldTop);

//      _ScrBbox[1] = tmp.X;
//      _ScrBbox[4] = tmp.Y;
      
//    }




//    public double Left
//    {
//      get { return _Bbox[2]; }
//    }




//    public double Bottom
//    {
//      get { return _Bbox[8]; }
//    }




//    public double Right
//    {
//      get { return _Bbox[1]; }
//    }




//    public double Top
//    {
//      get { return _Bbox[4]; }
//    }




//    public double Width
//    {
//      get { return Math.Abs(this.Right - this.Left); }
//    }




//    public double Height
//    {
//      get { return Math.Abs(this.Top - this.Bottom); }
//    }


//    //public double this[EdgeName edgeName]
//    //{
//    //  get { return _Bbox[(int)edgeName]; }
//    //}


//    public DisplayTransformMatrix DisplayTransform
//    {
//      get {return _transMatrix;}
//      set {_transMatrix = value;}
//    }



//    protected bool isValid(double left, double bottom, double right, double top)
//    {

//      if (left < right && bottom < top)
//        return true;
//      else
//        return false;
//    }




//    //int z = Convert.ToInt32("11001001", 2);
//    /* for line:
//     * for start point uses xxxx0000, first 4 bits
//     * for end point   uses 0000xxxx, last  4 bits
//     * for point only  uses xxxx0000, first 4 bits
//     * 
//     *         |        |
//     *   0110  |  0100  |  0101
//     *         |        |   
//     * --------------------------
//     *         |        |
//     *   0010  |  0000  |  0001
//     *         |        |
//     * --------------------------
//     *         |        |   
//     *   1010  |  1000  |  1001
//     *         |        |   
//     */
//    /*
//    internal int getLineIntesectMask(Point startP, Point endP)
//    {
//      int xs, xe;
//      int ys, ye;

//      xs = (startP.X <= _Bbox.left ? 2 : 0);
//      xs = (startP.X <= _Bbox.right && xs == 2 ? 2 : 1);
//      ys = (startP.Y <= _Bbox.bottom ? 8 : 0);
//      ys = (startP.Y <= _Bbox.top && ys == 8 ? 8 : 4);

//      xe = (endP.X <= _Bbox.left ? 32 : 0);
//      xe = (endP.X <= _Bbox.right && xe == 32 ? 32 : 16);
//      ye = (endP.Y <= _Bbox.bottom ? 128 : 0);
//      ye = (endP.Y <= _Bbox.top && ye == 128 ? 128 : 64);
//      return xs | ys | xe | ye;
//    }
    
//    */
//    protected internal int getPointIntesectMask(Point pnt)
//    {
//      int xs;
//      int ys;

//      xs = (pnt.X <= _Bbox[(int)EdgeName.left] ? 2 : 0);
//      xs = (pnt.X <= _Bbox[(int)EdgeName.right] && xs == 2 ? 2 : 1);
//      ys = (pnt.Y <= _Bbox[(int)EdgeName.bottom] ? 8 : 0);
//      ys = (pnt.Y <= _Bbox[(int)EdgeName.top] && ys == 8 ? 8 : 4);

//      return xs | ys;
//    }



//    private Point[] noIntersection = new Point[2]; //avoid reinitialization with each call

//    public Point[] lineIntersect(PointD startPoint, PointD endPoint)
//    {
      
//      Point startPt, endPt;

//      startPt = _transMatrix.TransformPoint(startPoint);
//      endPt = _transMatrix.TransformPoint(endPoint);

//      return lineIntersect(startPt, endPt);
//    }




//    public Point[] lineIntersect(Point startPoint, Point endPoint)
//    {

//      Point tmpPt;

//      //get point sone intersection mask
//      int ims = getPointIntesectMask(startPoint);
//      int ime = getPointIntesectMask(endPoint);

//      if ((ims | ime) == 0) //both inside of MapRegion
//      {
//        noIntersection[0] = startPoint;
//        noIntersection[1] = endPoint;
//        return noIntersection;
//      }

//      //one inside one outside, get intersection point and draw
//      else if ((ims | ime) != 0 && (ims == 0 || ime == 0))
//      {
//        if (ims == 0) //start point inside bbox
//          tmpPt = getIntersectionPoint(startPoint, endPoint, ime);
//        else          //end point inside bbox
//          tmpPt = getIntersectionPoint(startPoint, endPoint, ims);

//        noIntersection[0] = startPoint;
//        noIntersection[1] = tmpPt;
//        return noIntersection;
//      }

//      //none inside, different zones, can have 1-4 intersection points !!
//      else if ((ims | ime) != 0 && ims != 0 && ime != 0)
//      {
//        //XOR (^) gives full list of zones to search intersection for
//        List<Point> tmpPts = getOrderedIntersectionPoints(startPoint, endPoint, (ims ^ ime));
//        return tmpPts.ToArray();
//      }
//      else
//        return null; //no intersection
//    }





//    public Point[] lineIntersect(PointF startPt, PointF endPt)
//    {
//      PointD startPoint = new PointD();
//      PointD endPoint = new PointD();

//      startPoint.X = startPt.X;
//      startPoint.Y = startPt.Y;

//      endPoint.X = endPt.X;
//      endPoint.Y = endPt.Y; 
      
//      return lineIntersect(startPoint, endPoint);
//    }





//    protected internal List<Point> getOrderedIntersectionPoints(Point startP, Point endP, int im)
//    {
//      List<Point> tmpPts = new List<Point>();

//      if ((im & (int)(int)EdgeName.right) != 0) //resolve right edge
//        tmpPts.Add(getEdgeIntersectionPoint(startP, endP, EdgeName.right, true));

//      if ((im & (int)(int)EdgeName.top) != 0) //resolve top edge
//        tmpPts.Add(getEdgeIntersectionPoint(startP, endP, EdgeName.top, true));

//      if ((im & (int)(int)EdgeName.left) != 0) //resolve left edge
//        tmpPts.Add(getEdgeIntersectionPoint(startP, endP, EdgeName.left, true));

//      if ((im & (int)(int)EdgeName.bottom) != 0) //resolve bottom edge
//        tmpPts.Add(getEdgeIntersectionPoint(startP, endP, EdgeName.bottom, true));

//      //order all point by x or y distance from start point
//      tmpPts.Sort(new PointDistanceComparer(startP));
//      return tmpPts;
//    }




//    protected internal Point getIntersectionPoint(Point startP, Point endP, int im)
//    {
//      Point tmpPt;

//      if ((im & (int)(int)EdgeName.right) != 0) //resolve right edge
//      {
//        tmpPt = getEdgeIntersectionPoint(startP, endP, EdgeName.right, false);
//        if (this.Bottom <= tmpPt.Y || tmpPt.Y <= this.Top)
//          return tmpPt;
//      }

//      if ((im & (int)(int)EdgeName.top) != 0) //resolve top edge
//      {
//        tmpPt = getEdgeIntersectionPoint(startP, endP, EdgeName.top, false);
//        if (this.Left <= tmpPt.X || tmpPt.X <= this.Right)
//          return tmpPt;
//      }

//      if ((im & (int)EdgeName.left) != 0) //resolve left edge
//      {
//        tmpPt = getEdgeIntersectionPoint(startP, endP, EdgeName.left, false);
//        if (this.Bottom <= tmpPt.Y || tmpPt.Y <= this.Top)
//          return tmpPt;
//      }

//      if ((im & (int)EdgeName.bottom) != 0) //resolve bottom edge
//      {
//        tmpPt = getEdgeIntersectionPoint(startP, endP, EdgeName.bottom, false);
//        if (this.Left <= tmpPt.X || tmpPt.X <= this.Right)
//          return tmpPt;
//      }

//      throw new InvalidOperationException(); //never reach here !!

//    }




//    protected internal Point getEdgeIntersectionPoint(Point startP, Point endP, EdgeName intersectEdge, bool fitByEdge)
//    {

//      Point tmpPt = new Point();
//      int edgeId = (int)intersectEdge;

//      if (intersectEdge == EdgeName.left || intersectEdge == EdgeName.right)
//      {
//        tmpPt.Y = startP.Y + ((endP.Y - startP.Y) * (_ScrBbox[edgeId] - startP.X) / (endP.X - startP.X));
//        tmpPt.X = _ScrBbox[edgeId];
//      }
//      else
//      {
//        tmpPt.X = startP.X + ((endP.X - startP.X) * (_ScrBbox[edgeId] - startP.Y) / (endP.Y - startP.Y));
//        tmpPt.Y = _ScrBbox[edgeId];
//      }

//      if (fitByEdge)
//      {
//        if (tmpPt.Y < _ScrBbox[(int)EdgeName.bottom])
//          tmpPt.Y = _ScrBbox[(int)EdgeName.bottom];

//        if (tmpPt.Y > _ScrBbox[(int)EdgeName.top])
//          tmpPt.Y = _ScrBbox[(int)EdgeName.top];

//        if (tmpPt.X < _ScrBbox[(int)EdgeName.left])
//          tmpPt.X = _ScrBbox[(int)EdgeName.left];

//        if (tmpPt.X > _ScrBbox[(int)EdgeName.right])
//          tmpPt.X = _ScrBbox[(int)EdgeName.right];
//      }

//      return tmpPt;

//    }


//    /// <summary>
//    /// updates map world coordinate extent by given width and height 
//    /// of map display region (viewport) along current map center
//    /// </summary>
//    /// <param name="Width">viewport width</param>
//    /// <param name="Height">viewport htight</param>
//    public void Resize(float Width, float Height)
//    {

//      double WrldWidth = this.Right - this.Left;
//      double WrldHeight = this.Top - this.Bottom;
//      double ScaleX = Math.Abs(WrldWidth / Width);
//      double ScaleY = Math.Abs(WrldHeight / Height);

//      double TmpScale = ScaleX;
//      double OldWrldWidth = WrldWidth;
//      double OldWrldHeight = WrldHeight;

//      WrldWidth = Width * TmpScale;
//      WrldHeight = Height * TmpScale;


//      //_Bbox[2] = worldLeft;
//      //_Bbox[8] = worldBottom;
//      //_Bbox[1] = worldRight;
//      //_Bbox[4] = worldTop;


//      _Bbox[2] = (_Bbox[2] + ((OldWrldWidth - WrldWidth) / 2));
//      _Bbox[8] = (_Bbox[8] - ((OldWrldHeight - WrldHeight) / 2));
//      _Bbox[1] = (_Bbox[2] + WrldWidth);
//      _Bbox[4] = (_Bbox[8] - WrldHeight);


//      //update display transform matrix
//      _transMatrix.Translate(_Bbox[2], _Bbox[8]);


//      double scale = (this.Right - this.Left) / Width;
//      _transMatrix.Scale(scale, (-1) * scale);

//    }




//    public abstract BoundingBox Bounds { get; }
//    //{
//    //  get { return new BoundingBox(this.Left, this.Bottom, this.Right, this.Top); }
//    //}

//  }
//}
